
#ifndef  PAGE_H
#define  PAGE_H

#include "common.h"

class Page {
public:
    enum Status {
        Allocated,
        Sync,
        Dirty,
    };

    //for test
    static Page * newPage(const int32_t pageSize);
    static void freePage(Page* page);



    Page(PageNumberType pageNo, char * pageAddr, const int32_t pageSize);
    ~Page();

    const PageNumberType getNo() const {  return pageNo;}
    const uint32_t getSize() const { return pageSize;}

    char * getAddr(const int32_t offset = 0) const { return pageAddr + offset; }


    //for wrapper
    int writeString(const std::string & str){
        return writeBytes(str.c_str(), str.size(), 0, pageSize);
    }
    int writeString(const std::string & str, const int32_t offset, const int32_t length){
        return writeBytes(str.c_str(), str.size(), offset, length);
    }
    int writeBytes(const char * bytes, const int32_t srcLen){
        return writeBytes(bytes, srcLen, 0, pageSize);
    }
    int writeBytes(const char * val, const int32_t srcLen, const int32_t offset, const int32_t length);

    std::string readString(const int32_t offset, const int32_t length);
    std::string readBytes(const int32_t offset, const int32_t length);

    int writeByte(char v, const int32_t offset);
    int writeInt16(int16_t v, const int32_t offset);
    int writeUint16(uint16_t v, const int32_t offset);
    int writeInt32(int32_t v, const int32_t offset);
    int writeUint32(uint32_t v, const int32_t offset);
    int writeInt64(int64_t v, const int32_t offset);
    int writeUint64(uint64_t v, const int32_t offset);

    int readByte(const int32_t offset, char * v) const;
    int readInt16(const int32_t offset, int16_t * v) const;
    int readUint16(const int32_t offset, uint16_t * v) const;
    int readInt32(const int32_t offset, int32_t * v) const;
    int readUint32(const int32_t offset, uint32_t * v)const ;
    int readInt64(const int32_t offset, int64_t * v) const;
    int readUint64(const int32_t offset, uint64_t * v) const;

    //Page Status 
    bool isDirty() const { return status == Page::Dirty; }
    bool isAllocated() const { return status == Page::Allocated;}
    bool isSync() const { return status == Page::Sync;}
    void setStatusSync() { status = Page::Sync; }
    void setDirty() { if(status != Page::Dirty) {status = Page::Dirty; }}
    Page::Status getStatus() const { return status; }


    std::string hex(const int32_t offset, const int32_t length) const;
    const std::string toString() const;

private:
    PageNumberType pageNo;
    char * pageAddr;
    const int32_t pageSize;
    Page::Status status;
};

#endif   /* PAGE_H */
